{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. PP-LCNetV2 模型简介\n",
    "PP-LCNetV2 系列模型是 PaddleCV 团队提出的轻量级卷积神经网络模型，该系列模型基于 PP-LCNetv1 改进而来，更为侧重较高的模型性能，在 ImageNet1k 数据集上可以达到 77.04% 的精度，同时推理延时在 4.32ms 左右。另外，考虑到产业界大量使用 OpenVINO 推理框架的情况，PP-LCNetV2 系列模型针对 Intel CPU 硬件平台结合 OpenVINO 推理框架特别优化。\n",
    "\n",
    "PP-LCNetV2 系列模型基于 PaddleClas 开发、训练，更多关于 PP-LCNetV2 系列模型的更多信息，可以从 [PaddleClas-PPLCNetV2](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.5/docs/zh_CN/models/ImageNet1k/PP-LCNetV2.md) 获取。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 模型效果\n",
    "\n",
    "PP-LCNetV2 系列模型在 ImageNet1k 数据集上的评测指标如下所示：\n",
    "\n",
    "| Model | Params(M) | FLOPs(M) | Top-1 Acc(\\%) | Top-5 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
    "| <b>PPLCNetV2_base<b>  | <b>6.6<b> | <b>604<b>  | <b>77.04<b> | <b>93.27<b> | <b>4.32<b> |\n",
    "| <b>PPLCNetV2_base_ssld<b>  | <b>6.6<b> | <b>604<b>  | <b>80.07<b> | <b>94.87<b> | <b>4.32<b> |\n",
    "\n",
    "其中 `_ssld` 表示使用 `SSLD 蒸馏`后的模型。关于 `SSLD蒸馏` 的内容，详情 [SSLD 蒸馏](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.5/docs/zh_CN/training/advanced/knowledge_distillation.md)。\n",
    "\n",
    "与同量级其他轻量级网络的性能对比：\n",
    "\n",
    "| Model | Params(M) | FLOPs(M) | Top-1 Acc(\\%) | Top-5 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
    "| MobileNetV3_Large_x1_25 | 7.4 | 714  | 76.4 | 93.00 | 5.19 |\n",
    "| PPLCNetv1_x2_5  | 9 | 906  | 76.60 | 93.00 | 7.25 |\n",
    "| <b>PPLCNetV2_base<b>  | <b>6.6<b> | <b>604<b>  | <b>77.04<b> | <b>93.27<b> | <b>4.32<b> |\n",
    "| <b>PPLCNetV2_base_ssld<b>  | <b>6.6<b> | <b>604<b>  | <b>80.07<b> | <b>94.87<b> | <b>4.32<b> |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 模型快速使用\n",
    "\n",
    "### 3.1 模型推理：\n",
    "* 安装相关 Python 包\n",
    "\n",
    "（不在Jupyter Notebook上运行时需要将\"!\"去掉。）\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果您的机器安装了 CUDA9、CUDA10 或 CUDA11，请运行以下命令安装 paddle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install paddlepaddle-gpu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "您的机器是CPU，请运行以下命令安装 paddle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install paddlepaddle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "安装 paddleclas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "!pip install paddleclas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 快速体验\n",
    "\n",
    "恭喜！ 您已经成功安装了 PaddleClas，接下来快速体验图像分类效果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "!wget https://gitee.com/paddlepaddle/PaddleClas/raw/release/2.5/docs/images/inference_deployment/whl_demo.jpg\n",
    "!paddleclas --model_name=PPLCNetV2_base  --infer_imgs=\"./whl_demo.jpg\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上述命令的运行结果如下所示：\n",
    "\n",
    "class_ids: [8, 7, 86, 82, 83], scores: [0.8859, 0.07156, 0.00588, 0.00047, 0.00034], label_names: ['hen', 'cock', 'partridge', 'ruffed grouse, partridge, Bonasa umbellus', 'prairie chicken, prairie grouse, prairie fowl'], filename: docs/images/inference_deployment/whl_demo.jpg\n",
    "Predict complete"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 模型训练\n",
    "* PP-LCNetV2 系列模型基于 PaddleClas 实现，模型训练的具体信息请参考[模型训练、评估和预测](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.5/docs/zh_CN/models/ImageNet1k/PP-LCNetV2.md#3-%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83%E8%AF%84%E4%BC%B0%E5%92%8C%E9%A2%84%E6%B5%8B)。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 模型原理"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.1 总体结构\n",
    "\n",
    "PP-LCNetV2 网络的整体结构如下图所示：\n",
    "\n",
    "<div align=\"center\">\n",
    "<img src=\"https://user-images.githubusercontent.com/12560511/200776415-19f7f09d-f8e9-4b64-bbcd-72ac418c23cf.png\"  width = \"80%\"  />\n",
    "</div>\n",
    "\n",
    "### 4.2 模型细节\n",
    "\n",
    "PP-LCNetV2 模型是在 PP-LCNetV1 的基础上优化而来，主要使用重参数化策略组合了不同大小卷积核的深度卷积，并优化了点卷积、Shortcut等。\n",
    "\n",
    "#### 4.2.1 Rep 策略\n",
    "\n",
    "卷积核的大小决定了卷积层感受野的大小，通过组合使用不同大小的卷积核，能够获取不同尺度的特征，因此 PPLCNetV2 在 Stage4、Stage5 中，在同一层组合使用 kernel size 分别为 5、3、1 的 DW 卷积，同时为了避免对模型效率的影响，使用重参数化（Re parameterization，Rep）策略对同层的 DW 卷积进行融合，如下图所示。\n",
    "\n",
    "<div align=\"center\">\n",
    "<img src=\"https://user-images.githubusercontent.com/12560511/201664156-be8f5dc6-5345-436a-962e-079139f378d5.png\"  width = \"80%\"  />\n",
    "</div>\n",
    "\n",
    "#### 4.2.2 PW 卷积\n",
    "\n",
    "深度可分离卷积通常由一层 DW 卷积和一层 PW 卷积组成，用以替换标准卷积，为了使深度可分离卷积具有更强的拟合能力，我们尝试使用两层 PW 卷积，同时为了控制模型效率不受影响，两层 PW 卷积设置为：第一个在通道维度对特征图压缩，第二个再通过放大还原特征图通道，如下图所示。通过实验发现，该策略能够显著提高模型性能，同时为了平衡对模型效率带来的影响，PPLCNetV2 仅在 Stage4 中使用了该策略。\n",
    "\n",
    "<div align=\"center\">\n",
    "<img src=\"https://user-images.githubusercontent.com/12560511/201664376-e3cdd4ac-0767-4773-a6cc-b6885796bc1e.png\"  width = \"80%\"  />\n",
    "</div>\n",
    "\n",
    "#### 4.2.3 Shortcut\n",
    "\n",
    "残差结构（residual）自提出以来，被诸多模型广泛使用，但在轻量级卷积神经网络中，由于残差结构所带来的元素级（element-wise）加法操作，会对模型的速度造成影响，我们在 PP-LCNetV2 中，以 Stage 为单位实验了残差结构对模型的影响，发现残差结构的使用并非一定会带来性能的提高，因此 PPLCNetV2 仅在最后一个 Stage 中的使用了残差结构：在 Block 中增加 Shortcut，如下图所示。\n",
    "\n",
    "<div align=\"center\">\n",
    "<img src=\"https://user-images.githubusercontent.com/12560511/201664472-42139a13-28a1-43b9-92d7-d355f10ed56d.png\"  width = \"80%\"  />\n",
    "</div>\n",
    "\n",
    "#### 4.2.4 激活函数\n",
    "\n",
    "在目前的轻量级卷积神经网络中，ReLU、Hard-Swish 激活函数最为常用，虽然在模型性能方面，Hard-Swish 通常更为优秀，然而我们发现部分推理平台对于 Hard-Swish 激活函数的效率优化并不理想，因此为了兼顾通用性，PP-LCNetV2 默认使用了 ReLU 激活函数，并且我们测试发现，ReLU 激活函数对于较大模型的性能影响较小。\n",
    "\n",
    "\n",
    "#### 4.2.5 SE 模块\n",
    "\n",
    "虽然 SE 模块能够显著提高模型性能，但其对模型速度的影响同样不可忽视，在 PP-LCNetV1 中，我们发现在模型中后部使用 SE 模块能够获得最大化的收益。在 PP-LCNetV2 的优化过程中，我们以 Stage 为单位对 SE 模块的位置做了进一步实验，并发现在 Stage4 中使用能够取得更好的平衡。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 注意事项\n",
    "PP-LCNetV2 系列模型在 Intel CPU 端延时测试基于 Intel Xeon Gold 6271C 硬件平台完成，推理框架使用 OpenVINO 2021.4.2，推理 batch size 为 1，线程数为 10。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 相关论文以及引用信息"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
